﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using ZdfFlatUI.Utils;

namespace WpfToolkit
{
    [TemplatePart(Name = PART_Items, Type = typeof(ItemsControl))]
    public class CheckGroup : Control
    {
        static CheckGroup()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(CheckGroup), new FrameworkPropertyMetadata(typeof(CheckGroup)));
        }
        #region 变量
        private static readonly Type[] _baseTypes = new[] {
            typeof(bool), typeof(byte), typeof(sbyte), typeof(char), typeof(decimal),
            typeof(double), typeof(float),
            typeof(short), typeof(ushort), typeof(int), typeof(uint), typeof(long), typeof(ulong),
            typeof(string)
        };
        private List<object> _checkedItems;
        public const string PART_Items = "PART_Items";
        //private string groupType;
        #endregion
        #region 依赖属性
        public IEnumerable ItemsSource
        {
            get { return (IEnumerable)GetValue(ItemsSourceProperty); }
            set { SetValue(ItemsSourceProperty, value); }
        }

        /// <summary>
        /// For Internal Use Only. Identifies the <see cref="ItemsSource"/>Dependancy Property.
        /// </summary>
        public static readonly DependencyProperty ItemsSourceProperty =
            DependencyProperty.Register("ItemsSource", typeof(IEnumerable), typeof(CheckGroup),
                new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));

        public IEnumerable CheckedItems
        {
            get { return (IEnumerable)GetValue(CheckedItemsProperty); }
            set { SetValue(CheckedItemsProperty, value); }
        }

        // Using a DependencyProperty as the backing store for ChekedItems.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty CheckedItemsProperty =
            DependencyProperty.Register("CheckedItems", typeof(IEnumerable), typeof(CheckGroup),
                new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, new PropertyChangedCallback(OnCheckedItemsChanged)));

        public string GroupType
        {
            get { return (string)GetValue(GroupTypeProperty); }
            set { SetValue(GroupTypeProperty, value); }
        }

        // Using a DependencyProperty as the backing store for DisplayMemberPath.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty GroupTypeProperty =
            DependencyProperty.Register("GroupType", typeof(string), typeof(CheckGroup),
                new FrameworkPropertyMetadata(string.Empty));

        public string DisplayMemberPath
        {
            get { return (string)GetValue(DisplayMemberPathProperty); }
            set { SetValue(DisplayMemberPathProperty, value); }
        }

        // Using a DependencyProperty as the backing store for DisplayMemberPath.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty DisplayMemberPathProperty =
            DependencyProperty.Register("DisplayMemberPath", typeof(string), typeof(CheckGroup),
                new FrameworkPropertyMetadata(string.Empty));

        public bool IsThreeState
        {
            get { return (bool)GetValue(IsThreeStateProperty); }
            set { SetValue(IsThreeStateProperty, value); }
        }

        // Using a DependencyProperty as the backing store for IsThreeState.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty IsThreeStateProperty =
            DependencyProperty.Register("IsThreeState", typeof(bool), typeof(CheckGroup));


        public string GroupName
        {
            get { return (string)GetValue(GroupNameProperty); }
            set { SetValue(GroupNameProperty, value); }
        }

        public static readonly DependencyProperty GroupNameProperty =
            DependencyProperty.Register("GroupName", typeof(string), typeof(CheckGroup), new PropertyMetadata("DefaultGroup"));

        public string Text
        {
            get { return (string)GetValue(TextProperty); }
            set { SetValue(TextProperty, value); }
        }

        public static readonly DependencyProperty TextProperty =
            DependencyProperty.Register("Text", typeof(string), typeof(CheckGroup));


        public bool IsSelecteMode
        {
            get { return (bool)GetValue(IsSelecteModeProperty); }
            set { SetValue(IsSelecteModeProperty, value); }
        }

        // Using a DependencyProperty as the backing store for IsThreeState.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty IsSelecteModeProperty =
            DependencyProperty.Register("IsSelecteMode", typeof(bool), typeof(CheckGroup), new PropertyMetadata(false));

        public DataTemplate ItemTemplate
        {
            get { return (DataTemplate)GetValue(ItemTemplateProperty); }
            set { SetValue(ItemTemplateProperty, value); }
        }

        // Using a DependencyProperty as the backing store for CheckedItemTemplate.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ItemTemplateProperty =
            DependencyProperty.Register("ItemTemplate", typeof(DataTemplate), typeof(CheckGroup), new PropertyMetadata(null));
        private ItemsControl ItemsControl { get; set; }
        #endregion

        #region 方法

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            ItemsControl = Template.FindName(PART_Items, this) as ItemsControl;
            if (ItemsControl != null)
            {
                ItemsControl.PreviewMouseLeftButtonUp += PART_Items_PreviewMouseLeftButtonUp;
            }
            UpdateDisplayMemberTemplateSelector();
        }

        //渲染结束
        protected override void OnRender(DrawingContext drawingContext)
        {
            base.OnRender(drawingContext);

            SetCheckState();
        }

        //设置选中状态
        private void SetCheckState()
        {
            if (CheckedItems != null)
            {
                var newvalue = CheckedItems as List<object>;
                var checkBoxs = My2VisualTreeHelper.FindVisualChildren<CheckBox>(this.ItemsControl);
                if (checkBoxs != null && checkBoxs.Count() > 0)
                {
                    checkBoxs.ToList().ForEach(a =>
                    {
                        if (newvalue.Any(b => b.Equals(a.Tag)))
                        {
                            a.IsChecked = true;
                        }
                        else
                        {
                            a.IsChecked = false;
                        }
                    });
                }

                var radiobuttons = My2VisualTreeHelper.FindVisualChildren<RadioButton>(this.ItemsControl);
                if (radiobuttons != null && radiobuttons.Count() > 0)
                {
                    var checkItem = radiobuttons.ToList().FirstOrDefault(a => a.Tag.Equals(newvalue.FirstOrDefault()));
                    if (checkItem != null)
                    {
                        if (this.IsSelecteMode)
                        {
                            checkItem.IsChecked = false;
                        }
                        else
                        {
                            checkItem.IsChecked = true;
                        }
                    }
                }

            }
        }

        private void UpdateDisplayMemberTemplateSelector()
        {
            if (ItemsControl != null && ItemTemplate == null)
            {
                ItemsControl.ItemTemplateSelector = new CheckGroupTemlateSelector(DisplayMemberPath, GroupType, IsThreeState, GroupName);
            }
        }

        //private static void OnItemsSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        //{
        //    if (d is CheckGroup cg)
        //    {
        //        cg._checkedItems = null;
        //        cg.CheckedItems = null;
        //    }
        //}

        private static void OnCheckedItemsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (d is CheckGroup cg && e.OldValue != e.NewValue)
            {
                if (e.NewValue is List<object> newValue)
                {
                    cg._checkedItems = newValue;
                    cg.SetCheckState();
                    var lastitem = newValue.LastOrDefault();
                    cg.Text = lastitem?.GetType()?.GetProperty(cg.DisplayMemberPath)?.GetValue(lastitem, null).ToString();
                }
                else
                {
                    cg._checkedItems = null;
                    cg.Text = string.Empty;
                    var checkBoxs = My2VisualTreeHelper.FindVisualChildren<CheckBox>(cg.ItemsControl);
                    if (checkBoxs != null && checkBoxs.Count() > 0)
                    {
                        checkBoxs.ToList().ForEach(a => a.IsChecked = false);
                    }

                    var radiobuttons = My2VisualTreeHelper.FindVisualChildren<RadioButton>(cg.ItemsControl);
                    if (radiobuttons != null && radiobuttons.Count() > 0)
                    {
                        radiobuttons.ToList().ForEach(a =>
                        {
                            a.IsChecked = false;
                        });
                    }
                }
            }
        }

        private void PART_Items_PreviewMouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            if (e.OriginalSource is CheckBox cb)
            {
                if (_checkedItems == null)
                {
                    _checkedItems = new List<object>();
                }
                if (cb.IsChecked.HasValue && cb.IsChecked.Value)
                {
                    _checkedItems.Add(cb.Tag);
                }
                else
                {
                    _checkedItems.Remove(cb.Tag);
                }

                CheckedItems = new List<object>(_checkedItems);
            }
            else if (e.OriginalSource is RadioButton rb)
            {
                if (_checkedItems == null)
                {
                    _checkedItems = new List<object>();
                }
                _checkedItems.Clear();
                if (rb.IsChecked.HasValue && rb.IsChecked.Value)
                {
                    _checkedItems.Add(rb.Tag);
                    Text = rb.Content.ToString();
                }
                else
                {
                    Text = string.Empty;
                }

                CheckedItems = new List<object>(_checkedItems);
            }
        }

        #endregion
    }
}
